package per.hnvcam.searchext.controller.administration;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import per.hnvcam.hedge.algebra.Hedge2AlgebraDefinition;
import per.hnvcam.searchext.Constants;
import per.hnvcam.searchext.data.model.ConditionData;
import per.hnvcam.searchext.data.model.RuleData;
import per.hnvcam.searchext.data.model.SystemConfiguration;
import per.hnvcam.searchext.services.RuleService;
import per.hnvcam.searchext.services.SpecialQuery;

import javax.servlet.http.HttpServletRequest;

@Controller("RuleController")
public class RuleController {

   private static final String RULES_GENERATION_PAGE = "administration/rules";

   private static final String RULES_MANUAL_PAGE = "administration/manrules";

   private static final String CONDITION_COUNT_ELEMENT = "conditionCount";

   private static final String RULE_CLASS_ELEMENT = "ruleClass";

   private static final String WORD_ELEMENT = "word";

   private static final String VALUE_ELEMENT = "value";

   @Autowired
   @Qualifier("RuleService")
   private RuleService ruleService;

   @Autowired
   @Qualifier("SpecialQuery")
   private SpecialQuery specialQuery;

   @Autowired
   @Qualifier("Hedge2AlgebraDefinition")
   private Hedge2AlgebraDefinition hedge2AlgebraDefinition;

   @RequestMapping(value = "/administration/rules.jhtml", method = RequestMethod.GET)
   public String showRuleSet(@RequestParam(value = "operation", required = false) String operation, Model model) {
      if (Constants.OPERATION_GENERATE_BASE_RULES.equals(operation)) {
         ruleService.removeAllBaseRules();
         ruleService.generateBaseRules();
      }
      List<RuleData> baseRules = ruleService.getAllBaseRulesData();
      model.addAttribute("baseRules", baseRules);

      if (Constants.OPERATION_GENERATE_CLASSIFY_RULES.equals(operation)) {

         model.addAttribute("initialRuleSetSize", ruleService.generateInitialRules());
         List<RuleData> flooredRuleSet = ruleService.applyFlooringToInitialRules();
         model.addAttribute("flooringRuleSetSize", flooredRuleSet.size());
         List<RuleData> classifyRuleSet = ruleService.generateClassifyRuleSet(flooredRuleSet);
         ruleService.removeAllClassifyRules();
         ruleService.persistClassifyRuleSet(classifyRuleSet);
         model.addAttribute("classifyRuleSetSize", classifyRuleSet.size());
      }

      List<RuleData> classifyRules = ruleService.getClassifyRuleSet(false);
      model.addAttribute("classifyRuleSet", classifyRules);

      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("classifiedClasses", systemConfiguration.getClasses());

      return RULES_GENERATION_PAGE;
   }

   @RequestMapping(value = "/administration/manrules.jhtml", method = RequestMethod.GET)
   public String showManualRuleSet(Model model) {
      List<RuleData> manualRules = ruleService.getAllManualRulesData();
      model.addAttribute("manualRules", manualRules);
      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("classifiedClasses", systemConfiguration.getClasses());
      model.addAttribute("classChoiceList", getChoiceList(systemConfiguration.getClasses()));
      model.addAttribute("amountChoiceList", getChoiceList(hedge2AlgebraDefinition.getDomainOfLength(2)));
      return RULES_MANUAL_PAGE;
   }

   @RequestMapping(value = "/administration/manrules.jhtml", method = RequestMethod.POST)
   public String addNewRule(HttpServletRequest request, Model model) {
      int conditionCount = Integer.parseInt(request.getParameter(CONDITION_COUNT_ELEMENT));
      String classifiedClass = request.getParameter(RULE_CLASS_ELEMENT);

      List<ConditionData> conditionList = new ArrayList<ConditionData>();
      for (int i = 0; i < conditionCount; i++) {
         ConditionData cond = new ConditionData();
         cond.setWord(request.getParameter(WORD_ELEMENT + i));
         cond.setFuzzyAmount(request.getParameter(VALUE_ELEMENT + i));
         conditionList.add(cond);
      }

      ruleService.addManualRule(conditionList, classifiedClass);

      List<RuleData> manualRules = ruleService.getAllManualRulesData();
      model.addAttribute("manualRules", manualRules);
      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("classifiedClasses", systemConfiguration.getClasses());
      model.addAttribute("classChoiceList", getChoiceList(systemConfiguration.getClasses()));
      model.addAttribute("amountChoiceList", getChoiceList(hedge2AlgebraDefinition.getDomainOfLength(2)));
      return RULES_MANUAL_PAGE;
   }

   private String getChoiceList(Map<String, String> map) {
      String result = "";
      for (String key : map.keySet()) {
         result += "<option value='" + key + "'>" + map.get(key) + "</option>";
      }
      return result;
   }

   private String getChoiceList(Collection<String> list) {
      String result = "";
      for (String value : list) {
         result += "<option value='" + value + "'>" + value + "</option>";
      }
      return result;
   }


}
